package com.jumi.microservice.service.logistics.admin;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.bean.ProducerBean;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.jumi.microservice.common.redis.RedisCache;
import com.jumi.microservice.common.utils.DateUtil;
import com.jumi.microservice.config.TimeConfiguration;
import com.jumi.microservice.domain.GoodsSkuMaterialDTO;
import com.jumi.microservice.domain.MessageTemplate;
import com.jumi.microservice.dto.excel.ImportNoSelfResponse;
import com.jumi.microservice.dto.logistics.excel.SelfWaitSend;
import com.jumi.microservice.dto.reponse.UserExternalResponse;
import com.jumi.microservice.entity.*;
import com.jumi.microservice.enumerate.LogisticsStatusEnum;
import com.jumi.microservice.enumerate.OrderStatusEnum;
import com.jumi.microservice.mapper.*;
import com.jumi.microservice.material.service.IJmWarehouseService;
import com.jumi.microservice.rocketmq.SendMessageHandler;
import com.jumi.microservice.service.BasicDataApi;
import com.jumi.microservice.service.BasicDataService;
import com.jumi.microservice.service.IMemberService;
import com.jumi.microservice.service.IUserExternalService;
import com.jumi.microservice.warehouseout.api.ApiChangeShippingCodeService;
import com.jumi.microservice.warehouseout.vo.JmOrderWarehouseOutVo;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class AsyncSendService {


    private static final Logger log = LoggerFactory.getLogger(AsyncSendService.class);
    @Resource
    LogisticsGoodsMapper logisticsGoodsMapper;

    @Resource
    OrderGoodsMapper orderGoodsMapper;

    @Resource
    UserOrderMapper userOrderMapper;

    @Resource
    OrderLogisticsMapper orderLogisticsMapper;

    @DubboReference
    BasicDataApi iExpressService;

    @DubboReference
    BasicDataService basicDataService;

//    @DubboReference
//    ApiOrderWarehouseOutService iMaterialService;

    @DubboReference
    IMemberService iMemberService;

    @DubboReference
    ApiChangeShippingCodeService iChangeLogisticsNoService;

    @Resource
    SendMessageHandler sendMessageHandler;

    @Resource
    OrderLogMapper orderLogMapper;
    @Resource
    ProducerBean producerBean;
    @Resource
    TimeConfiguration timeConfiguration;
    @Resource
    RedisCache redisCache;
    @DubboReference
    private IUserExternalService userExternalService;
    @DubboReference
    IJmWarehouseService iWarehouseService;


    /**
     * 判断是否是取消商品
     * @param orderNo
     * @param goodsId
     * @return
     */
    public boolean isGoodsStatusCancel(String orderNo,Integer goodsId){
        QueryWrapper<OrderGoods> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_no",orderNo).eq("goods_id",goodsId).eq("goods_status", LogisticsStatusEnum.CANCEL.getCode());
        int count = orderGoodsMapper.selectCount(queryWrapper);
        return count >0;
    }

    @Async
    public void batchSelfSendMessage(MessageTemplate messageTemplate, List<SelfWaitSend> selfWaitSends, List<String> errorList) {
        if (selfWaitSends.isEmpty() || !errorList.isEmpty()) {
            return;
        }
        List<String> orderNos = new ArrayList<>();
        for (SelfWaitSend selfWaitSend : selfWaitSends) {
            if(isGoodsStatusCancel(selfWaitSend.getOrderNo(),selfWaitSend.getGoodsId())
                    || orderNos.contains(selfWaitSend.getOrderNo())){
                continue;
            }
            sendMessage(messageTemplate, selfWaitSend);
            orderNos.add(selfWaitSend.getOrderNo());
        }
    }

    @Async
    public void batchAddLog(List<JSONObject> list, List<String> errorList) {
        if (list.isEmpty() || !errorList.isEmpty()) {
            return;
        }
        for (JSONObject jsonObject : list) {
            if(isGoodsStatusCancel(jsonObject.getString("orderNo"),jsonObject.getInteger("goodsId"))){
                continue;
            }
            addLog(jsonObject.getLong("uid"), jsonObject.getString("name")
                    , jsonObject.getString("orderNo"), jsonObject.getString("log"));
        }
    }

    public void sendMessage(MessageTemplate messageTemplate, SelfWaitSend selfWaitSend) {
        String appMessageContent = messageTemplate == null ? "" : messageTemplate.getSmtAppContent()
                .replace("{}", selfWaitSend.getLogisticsCompany());
        String stationMessageContent = messageTemplate == null ? "" : messageTemplate.getSmtMessageContent()
                .replace("{}", selfWaitSend.getLogisticsCompany());
        String smtShortContent = messageTemplate == null ? "" : messageTemplate.getSmtShortContent()
                .replace("{$logisticsNo}", selfWaitSend.getRealLogisticsNo());
        QueryWrapper<OrderGoods> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_id", selfWaitSend.getOrderId()).last("limit 1");
        OrderGoods orderGoods = orderGoodsMapper.selectOne(queryWrapper);
        sendMessageHandler.sendMessage(selfWaitSend.getOrderNo(), appMessageContent, stationMessageContent,
                smtShortContent, selfWaitSend.getRealLogisticsNo(), selfWaitSend.getReceiverPhone(), orderGoods.getGoodsCoverImg(),
                selfWaitSend.getBuyId(), 4, BigDecimal.ZERO, BigDecimal.ZERO, "", (byte) 0);
    }

//    @Async
//    @Transactional(rollbackFor = Exception.class)
//    public void selfSendBatchUpdate(List<OrderLogistics> orderLogisticsList, List<Integer> orderIds,
//                                    List<OrderGoods> orderGoodsList, List<LogisticsGoods> sendGoodsList, List<String> selfWaitSendError) {
//        if (!selfWaitSendError.isEmpty()) {
//            return;
//        }
//        if (!sendGoodsList.isEmpty()) {
//            logisticsGoodsMapper.updateSend(sendGoodsList);
//        }
//        if (!orderLogisticsList.isEmpty()) {
//            orderLogisticsMapper.batchUpdateLogisticsStatus(orderLogisticsList);
//        }
//        if (!orderGoodsList.isEmpty()) {
//            orderGoodsMapper.batchUpdateGoodsStatus(orderGoodsList);
//        }
//        if (!orderIds.isEmpty()) {
//            batchUpdateOrderStatusAndConfirmTime(orderIds);
//        }
//    }

    @Async
    @Transactional(rollbackFor = Exception.class)
    public void selfUpdateLogisticsGoods(List<LogisticsGoods> sendGoodsList, List<String> selfWaitSendError){
        if (!selfWaitSendError.isEmpty()) {
            return;
        }
        if (!sendGoodsList.isEmpty()) {
            logisticsGoodsMapper.updateSend(sendGoodsList);
        }
    }
    @Async
    @Transactional(rollbackFor = Exception.class)
    public void selfUpdateOrderLogistics(List<OrderLogistics> orderLogisticsList,List<String> selfWaitSendError){
        if (!selfWaitSendError.isEmpty()) {
            return;
        }
        if (!orderLogisticsList.isEmpty()) {
            orderLogisticsMapper.batchUpdateLogisticsStatus(orderLogisticsList);
        }
    }
    @Async
    @Transactional(rollbackFor = Exception.class)
    public void selfUpdateOrderGoods(List<OrderGoods> orderGoodsList, List<String> selfWaitSendError){
        if (!selfWaitSendError.isEmpty()) {
            return;
        }
        if (!orderGoodsList.isEmpty()) {
            orderGoodsMapper.batchUpdateGoodsStatus(orderGoodsList);
        }
    }

    /**
     * 批量修改订单状态以及自动确认收货时间
     *
     * @param orderIds
     */
    @Async
    @Transactional(rollbackFor = Exception.class)
    public void selfBatchUpdateOrderStatusAndConfirmTime(List<Integer> orderIds,List<String> errorList) {
        if(!errorList.isEmpty() ||orderIds.isEmpty()){
            return;
        }
        UpdateWrapper<UserOrder> userOrderUpdateWrapper = new UpdateWrapper<>();
        userOrderUpdateWrapper.in("id", orderIds)
                .and(q -> q.eq("order_status", OrderStatusEnum.READY_TO_SHIP.getCode()).or()
                        .eq("order_status", OrderStatusEnum.READY_TO_RECEIVE.getCode()).isNull("confirm_time"));
        UserOrder userOrder = new UserOrder();
        userOrder.setOrderStatus(OrderStatusEnum.READY_TO_RECEIVE.getCode());
        userOrder.setConfirmTime(DateUtil.getDateAfterMinute(new Date(),
                Integer.parseInt(timeConfiguration.getConfirmTimeMinutes())));
        userOrderMapper.update(userOrder, userOrderUpdateWrapper);
    }

    public void noticeMaterialNew(LogisticsGoods logisticsGoods, Map<Integer, GoodsSkuMaterialDTO> materialDTOMap, String name) {
        GoodsSkuMaterialDTO goodsSkuMaterialDTO = null;
        JmOrderWarehouseOutVo jmOrderWarehouseOutVo = new JmOrderWarehouseOutVo();
        if (materialDTOMap.containsKey(logisticsGoods.getGoodsId())) {
            goodsSkuMaterialDTO = materialDTOMap.get(logisticsGoods.getGoodsId());
        }
        String key = "user_info::".concat(logisticsGoods.getBuyerId().toString());
        Map<String, Object> userInfoCacheMap = redisCache.getCacheMap(key);
        String buyerName = "";
        String buyerMobile = "";
        if (userInfoCacheMap == null || userInfoCacheMap.size() == 0) {
            UserExternalResponse user = userExternalService.getUserByUid(logisticsGoods.getBuyerId().intValue());
            if (user != null) {
                buyerName = user.getNickName();
                buyerMobile = user.getMobile();
            }
        } else {
            if (userInfoCacheMap.containsKey(key)) {
                buyerName = userInfoCacheMap.get("name").toString();
                buyerMobile = userInfoCacheMap.get("mobile").toString();
            }
        }
        jmOrderWarehouseOutVo.setBuyerMessage(buyerName + " " + buyerMobile);
        jmOrderWarehouseOutVo.setX(logisticsGoods.getRealSendAmount());
        jmOrderWarehouseOutVo.setBuyerDetail(logisticsGoods.getReceiverName()
                + logisticsGoods.getReceiverPhone() + " " + logisticsGoods.getReceiverAddress());
        jmOrderWarehouseOutVo.setMaterialSkuRelationshipDTOList(goodsSkuMaterialDTO != null ?
                goodsSkuMaterialDTO.getMaterialSkuRelationship() : new ArrayList<>());
        jmOrderWarehouseOutVo.setSupplierId(logisticsGoods.getSupplierId());
        jmOrderWarehouseOutVo.setShippingCode(logisticsGoods.getRealLogisticsNo());
        jmOrderWarehouseOutVo.setSendWarehouseId(logisticsGoods.getRealWarehouse());
        jmOrderWarehouseOutVo.setOperator(name);
        jmOrderWarehouseOutVo.setRemark(logisticsGoods.getRemark() == null ? "" : logisticsGoods.getRemark());
        try {
            Message sendMessage = new Message("orderOut", "", "", JSON.toJSONBytes(jmOrderWarehouseOutVo));
            producerBean.send(sendMessage);
            log.info("发送订单物料出库队列成功 [{}]", JSON.toJSONString(jmOrderWarehouseOutVo));
        } catch (Exception e) {
            log.info("发送订单物料出库队列失败 [{}]", e.getMessage());
        }
    }

    /**
     * 获取物料信息
     *
     * @param goodsId
     * @return
     */
    public Map<Integer, GoodsSkuMaterialDTO> getMaterialMap(List<Long> goodsId) {
        //请求接口获取物料信息
        List<GoodsSkuMaterialDTO> materialDTOS = basicDataService.getMaterialSkuRelationshipByIds(goodsId);
        return materialDTOS.stream().distinct().collect(Collectors.toMap(g -> g.getSkuId().intValue(), g -> g, (oldValue, newValue) -> newValue));
    }

    /**
     * 通知物料出库
     *
     * @param goodsList
     */
    @Async
    public void noticeMaterial(List<LogisticsGoods> goodsList, List<Long> goodsIds, String name, List<String> selfWaitSendError) {
        if (goodsList.isEmpty() || !selfWaitSendError.isEmpty()) {
            return;
        }
        //获取物料信息
        Map<Integer, GoodsSkuMaterialDTO> materialDTOMap = getMaterialMap(goodsIds);
        for (LogisticsGoods logisticsGoods : goodsList) {
            if(isGoodsStatusCancel(logisticsGoods.getOrderNo(),logisticsGoods.getGoodsId())){
                continue;
            }
            noticeMaterialNew(logisticsGoods, materialDTOMap, name);
        }
    }

    /**
     * 插入日志记录表
     *
     * @param uid
     * @param name
     * @param orderNo
     * @param log
     */
    public boolean addLog(Long uid, String name, String orderNo, String log) {
        OrderLog orderLog = new OrderLog();
        orderLog.setOperatorId(uid);
        orderLog.setOperatorName(name);
        orderLog.setOrderSn(orderNo);
        orderLog.setLog(log);
        orderLog.setUserFlag((byte) 2);
        int rows = orderLogMapper.insert(orderLog);
        return rows > 0;
    }

//    @Async
//    @Transactional(rollbackFor = Exception.class)
//    public void partSendUpdate(List<OrderGoods> goodsList, List<LogisticsGoods> logisticsGoodsList,
//                               List<LogisticsGoods> insertLogisticsGoodsList, List<String> partSendError) {
//        if (!partSendError.isEmpty()) {
//            return;
//        }
//        if (!goodsList.isEmpty()) {
//            orderGoodsMapper.batchUpdateGoodsStatusPartSend(goodsList);
//        }
//        if (!logisticsGoodsList.isEmpty()) {
//            logisticsGoodsMapper.partSend(logisticsGoodsList);
//        }
//        if (!insertLogisticsGoodsList.isEmpty()) {
//            logisticsGoodsMapper.batchInsertGoodsPartSend(insertLogisticsGoodsList);
//        }
//    }

    @Async
    @Transactional(rollbackFor = Exception.class)
    public void partUpdateGoods(List<OrderGoods> goodsList,List<String> partSendError){
        if (!partSendError.isEmpty()) {
            return;
        }
        if (!goodsList.isEmpty()) {
            orderGoodsMapper.batchUpdateGoodsStatusPartSend(goodsList);
        }
    }
    @Async
    @Transactional(rollbackFor = Exception.class)
    public void partUpdateLogisticsGoods(List<LogisticsGoods> logisticsGoodsList,List<String> partSendError){
        if (!partSendError.isEmpty()) {
            return;
        }
        if (!logisticsGoodsList.isEmpty()) {
            logisticsGoodsMapper.partSend(logisticsGoodsList);
        }
    }
    @Async
    @Transactional(rollbackFor = Exception.class)
    public void partInsertLogisticsGoods(List<LogisticsGoods> insertLogisticsGoodsList,List<String> partSendError){
        if (!partSendError.isEmpty()) {
            return;
        }
        if (!insertLogisticsGoodsList.isEmpty()) {
            logisticsGoodsMapper.batchInsertGoodsPartSend(insertLogisticsGoodsList);
        }
    }


    @Async
    public void batchNoSelfSendMessage(MessageTemplate messageTemplate, List<ImportNoSelfResponse> importNoSelfResponses, Map<String, String> coverImgUrlMap, List<String> errorList) {
        if (importNoSelfResponses.isEmpty() || !errorList.isEmpty()) {
            return;
        }
        List<String> orderNos = new ArrayList<>();
        for (ImportNoSelfResponse importNoSelfResponse : importNoSelfResponses) {
            if(isGoodsStatusCancel(importNoSelfResponse.getOrderNo(),importNoSelfResponse.getGoodsId())
                    || orderNos.contains(importNoSelfResponse.getOrderNo())){
                continue;
            }
            String coverImgUrl = "";
            if (coverImgUrlMap.containsKey(importNoSelfResponse.getOrderNo() + importNoSelfResponse.getGoodsId())) {
                coverImgUrl = coverImgUrlMap.get(importNoSelfResponse.getOrderNo() + importNoSelfResponse.getGoodsId());
            }
            noSelfSendMessage(messageTemplate, importNoSelfResponse, coverImgUrl);
            orderNos.add(importNoSelfResponse.getOrderNo());
        }
    }

    public void noSelfSendMessage(MessageTemplate messageTemplate, ImportNoSelfResponse importNoSelfResponse, String coverImgUrl) {
        String appMessageContent = messageTemplate == null ? "" : messageTemplate.getSmtAppContent()
                .replace("{}", importNoSelfResponse.getExpressCompany());
        String stationMessageContent = messageTemplate == null ? "" : messageTemplate.getSmtMessageContent()
                .replace("{}", importNoSelfResponse.getExpressCompany());
        String smtShortContent = messageTemplate == null ? "" : messageTemplate.getSmtShortContent()
                .replace("{$logisticsNo}", importNoSelfResponse.getRealLogisticsNo());
        sendMessageHandler.sendMessage(importNoSelfResponse.getOrderNo(), appMessageContent, stationMessageContent,
                smtShortContent, importNoSelfResponse.getRealLogisticsNo(), importNoSelfResponse.getPhone(),
                coverImgUrl, importNoSelfResponse.getBuyerId(), 4, BigDecimal.ZERO,
                BigDecimal.ZERO, "", (byte) 0);
    }

    @Async
    @Transactional(rollbackFor = Exception.class)
    public void noSelfSendUpdate(List<UserOrder> userOrders, List<OrderGoods> orderGoods,
                                 List<LogisticsGoods> logisticsGoodsList, List<OrderLogistics> orderLogisticsList, List<String> noSelfWaitSendError) {
        if (!noSelfWaitSendError.isEmpty()) {
            return;
        }
        if (!orderGoods.isEmpty()) {
            orderGoodsMapper.batchUpdateGoodsStatus(orderGoods);
        }
        if (!userOrders.isEmpty()) {
            userOrderMapper.batchUpdateOrderConfirmTime(userOrders);
        }
        if (!logisticsGoodsList.isEmpty()) {
            logisticsGoodsMapper.noSelfSend(logisticsGoodsList);
        }
        if (!orderLogisticsList.isEmpty()) {
            orderLogisticsMapper.batchUpdateLogisticsStatus(orderLogisticsList);
        }
    }

    @Async
    @Transactional(rollbackFor = Exception.class)
    public void noSelfUpdateOrderGoods(List<OrderGoods> orderGoods,List<String> noSelfWaitSendError){
        if (!noSelfWaitSendError.isEmpty()) {
            return;
        }
        if (!orderGoods.isEmpty()) {
            orderGoodsMapper.batchUpdateGoodsStatus(orderGoods);
        }
    }
    @Async
    @Transactional(rollbackFor = Exception.class)
    public void noSelfUpdateUserOrder(List<UserOrder> userOrders,List<String> noSelfWaitSendError){
        if (!noSelfWaitSendError.isEmpty()) {
            return;
        }
        if (!userOrders.isEmpty()) {
            userOrderMapper.batchUpdateOrderConfirmTime(userOrders);
        }
    }
    @Async
    @Transactional(rollbackFor = Exception.class)
    public void noSelfLogisticsGoods(List<LogisticsGoods> logisticsGoodsList,List<String> noSelfWaitSendError){
        if (!noSelfWaitSendError.isEmpty()) {
            return;
        }
        if (!logisticsGoodsList.isEmpty()) {
            logisticsGoodsMapper.noSelfSend(logisticsGoodsList);
        }
    }
    @Async
    @Transactional(rollbackFor = Exception.class)
    public void noSelfUpdateOrderLogistics(List<OrderLogistics> orderLogisticsList,List<String> noSelfWaitSendError){
        if (!noSelfWaitSendError.isEmpty()) {
            return;
        }
        if (!orderLogisticsList.isEmpty()) {
            orderLogisticsMapper.batchUpdateLogisticsStatus(orderLogisticsList);
        }
    }


    @Async
    public void batchUpdateOrderStatus(List<Integer> orderIds) {
        //批量发货
        if (!orderIds.isEmpty()) {
            UpdateWrapper<UserOrder> userOrderUpdateWrapper = new UpdateWrapper<>();
            userOrderUpdateWrapper.in("id", orderIds);
            userOrderUpdateWrapper.eq("order_status", OrderStatusEnum.READY_TO_SHIP.getCode());
            UserOrder userOrder = new UserOrder();
            userOrder.setOrderStatus(OrderStatusEnum.READY_TO_RECEIVE.getCode());
            userOrderMapper.update(userOrder, userOrderUpdateWrapper);
        }
    }

}
